package cn.xchats.rpc.client;

import cn.xchats.rpc.client.load.LoadBalance;
import cn.xchats.rpc.client.load.LoadBalanceTcpClient;
import cn.xchats.rpc.common.annotation.RpcReference;
import cn.xchats.rpc.common.annotation.RpcService;
import cn.xchats.rpc.common.core.CacheBeanMethod;
import cn.xchats.rpc.common.core.Invoke;
import cn.xchats.rpc.common.dto.BeanMethod;
import cn.xchats.rpc.common.dto.RequestDto;
import cn.xchats.rpc.common.dto.ResponseDto;
import org.apache.zookeeper.data.Id;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Map;

/*
 *中介服务
 * 每个bean实例化的时候 都会执行当前class
 *@author teddy
 *@date 2018/6/29
 */
@Component
public class ClientMediator implements BeanPostProcessor {

    private static final String[] noExecuteMethodNameArray = {"toString"};

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Class<?> beanClass = bean.getClass();

        Field[] beanFieldArray = beanClass.getDeclaredFields();
        for (int i = 0; i < beanFieldArray.length; i++) {
            Field field = beanFieldArray[i];
            if (field.isAnnotationPresent(RpcReference.class)) {
                field.setAccessible(true);
                //proxy
                Enhancer enhancer = new Enhancer();
                //设置proxy实现的接口
                enhancer.setInterfaces(new Class[]{field.getType()});

                //拦截方法
                enhancer.setCallback((MethodInterceptor) (instance, method, args, proxy) -> {
                    if (!selectExecuteMethod(method.getName()))
                        return null;
                    String methodParameter = Invoke.convertMethodParameter(instance.getClass(), method);
                    //发送
                    RequestDto request = new RequestDto<>();
                    request.setMethod(methodParameter);
                    //有参数的方法

                    Object parameters;
                    if (0 == args.length)
                        parameters = null;
                    if (1 == args.length)
                        parameters = args[0];
                    else
                        parameters = args;

                    request.setBody(parameters);
                    ResponseDto result = LoadBalanceTcpClient.send(request);//TcpClient.send(request);
                    if (null == result)
                        return request;
                    return result.getBody();
                });

                //创建proxy
                try {
                    field.set(bean, enhancer.create());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    System.out.println("创建代理类出错 > > > > > " + beanName);
                    System.exit(0);
                }
            }
        }


        return bean;
    }

    /**
     * 初始化完bean之后执行该方法
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }


    /**
     * 是否执行方法
     */
    public boolean selectExecuteMethod(String name) {
        for (int i = 0; i < noExecuteMethodNameArray.length; i++) {
            String noExecuteMethodName = noExecuteMethodNameArray[i];
            if (noExecuteMethodName.equals(name))
                return false;
        }
        return true;
    }

}
